package com.tiancheng.trade.settlement.service.settlement.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.tiancheng.trade.commom.core.data.PageInfo;
import com.tiancheng.trade.commom.core.data.Result;
import com.tiancheng.trade.commom.core.utils.DateTimeUtil;
import com.tiancheng.trade.settlement.bo.ProductBO;
import com.tiancheng.trade.settlement.enums.*;
import com.tiancheng.trade.settlement.exception.error.BusinessErrorInfoEnum;
import com.tiancheng.trade.settlement.feign.MerchantPaymentChannelService;
import com.tiancheng.trade.settlement.mapper.settlement.SettlementRuleMapper;
import com.tiancheng.trade.settlement.model.settlement.SettlementRule;
import com.tiancheng.trade.settlement.model.settlement.SettlementRuleExp;
import com.tiancheng.trade.settlement.service.settlement.ISettlementRuleService;
import com.tiancheng.trade.settlement.util.*;
import com.tiancheng.trade.settlement.util.cache.SettleCache;
import com.tiancheng.trade.settlement.vo.settlement.api.GetSettlementRuleVO;
import com.tiancheng.trade.settlement.vo.settlement.api.OpenAddRuleVO;
import com.tiancheng.trade.settlement.vo.settlement.api.OpenDeleteRuleVO;
import com.tiancheng.trade.settlement.vo.settlement.api.SettlementRuleVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
public class SettlementRuleService implements ISettlementRuleService {

    @Autowired
    SettlementRuleMapper settlementMapper;
    @Resource
    private IdGenerateUtil idGenerateUtil;
    @Resource
    private MerchantPaymentChannelService merchantPaymentChannelService;

    /**
     * 允许通过接口导入清分规则的场景
     */
    private static final List<String> OPEN_SETTLE_RULE_SOURCE = new ArrayList<String>() {};

    @Override
    public SettlementRule findById(Long id) {
        SettlementRule rule = settlementMapper.selectById(id);
        if (null != rule) {
            getSettlementRuleReceivable(rule);
            setSettlementEnum(rule);
        }
        return rule;
    }

    @Override
    public PageInfo<SettlementRule> getSettlementRule(GetSettlementRuleVO settlementRuleVO) {
        QueryWrapper<SettlementRule> conditions = new QueryWrapper<SettlementRule>();
        conditions.eq("is_delete", "0");
        if (StringUtils.isNotEmpty(settlementRuleVO.getMerchantName())) {
            conditions.like("merchant_name", settlementRuleVO.getMerchantName());
        }
        if (StringUtils.isNotEmpty(settlementRuleVO.getProductName())) {
            conditions.like("product_name", settlementRuleVO.getProductName());
        }
        if (StringUtils.isNotEmpty(settlementRuleVO.getProductCode())) {
            conditions.eq("product_code", settlementRuleVO.getProductCode());
        }
        if (StringUtils.isNotEmpty(settlementRuleVO.getRuleCode())) {
            conditions.eq("rule_code", settlementRuleVO.getRuleCode());
        }
        if (StringUtils.isNotEmpty(settlementRuleVO.getRuleName())) {
            conditions.like("rule_name", settlementRuleVO.getRuleName());
        }
        if (StringUtils.isNotEmpty(settlementRuleVO.getRuleType())) {
            conditions.eq("rule_type", settlementRuleVO.getRuleType());
        }
        if (StringUtils.isNotEmpty(settlementRuleVO.getSettlementType())) {
            conditions.eq("settlement_type", settlementRuleVO.getSettlementType());
        }
        if (StringUtils.isNotEmpty(settlementRuleVO.getClearingRule())) {
            conditions.eq("clearing_rule", settlementRuleVO.getClearingRule());
        }
        if (StringUtils.isNotEmpty(settlementRuleVO.getSettlementStatus())) {
            conditions.eq("settlement_status", settlementRuleVO.getSettlementStatus());
        }
        if (null != settlementRuleVO.getEffectiveDate()) {
            conditions.ge("expire_date", settlementRuleVO.getExpireDate());
        }
        if (null != settlementRuleVO.getExpireDate()) {
            conditions.le("effective_date", settlementRuleVO.getEffectiveDate());
        }
        conditions.orderByDesc("created_dt");
        PageInfo<SettlementRule> pageInfo = settlementMapper.find(conditions, settlementRuleVO.getCurrentPage(), settlementRuleVO.getPageSize());

        if (CollectionUtils.isNotEmpty(pageInfo.getList())) {
            pageInfo.getList().forEach(a -> {
                setSettlementEnum(a);
            });
        }
        return pageInfo;
    }


    @Override
    public List<SettlementRule> getSettlementRuleList(GetSettlementRuleVO settlementRuleVO) {
        QueryWrapper<SettlementRule> conditions = new QueryWrapper<SettlementRule>();
        conditions.eq("is_delete", "0");
        if (StringUtils.isNotEmpty(settlementRuleVO.getMerchantName())) {
            conditions.like("merchant_name", settlementRuleVO.getMerchantName());
        }
        if (StringUtils.isNotEmpty(settlementRuleVO.getProductName())) {
            conditions.like("product_name", settlementRuleVO.getProductName());
        }
        if (StringUtils.isNotEmpty(settlementRuleVO.getProductCode())) {
            conditions.eq("product_code", settlementRuleVO.getProductCode());
        }
        if (StringUtils.isNotEmpty(settlementRuleVO.getRuleCode())) {
            conditions.eq("rule_code", settlementRuleVO.getRuleCode());
        }
        if (StringUtils.isNotEmpty(settlementRuleVO.getRuleName())) {
            conditions.like("rule_name", settlementRuleVO.getRuleName());
        }
        if (StringUtils.isNotEmpty(settlementRuleVO.getRuleType())) {
            conditions.eq("rule_type", settlementRuleVO.getRuleType());
        }
        if (StringUtils.isNotEmpty(settlementRuleVO.getSettlementType())) {
            conditions.eq("settlement_type", settlementRuleVO.getSettlementType());
        }
        if (StringUtils.isNotEmpty(settlementRuleVO.getClearingRule())) {
            conditions.eq("clearing_rule", settlementRuleVO.getClearingRule());
        }
        if (StringUtils.isNotEmpty(settlementRuleVO.getSettlementStatus())) {
            conditions.eq("settlement_status", settlementRuleVO.getSettlementStatus());
        }
        if (null != settlementRuleVO.getEffectiveDate()) {
            conditions.ge("effective_date", settlementRuleVO.getEffectiveDate() + " 00:00:00");
        }
        if (null != settlementRuleVO.getExpireDate()) {
            conditions.le("expire_date", settlementRuleVO.getExpireDate() + " 23:59:59");
        }
        if (null != settlementRuleVO.getPriorityLevel()) {
            conditions.eq("priority_level", settlementRuleVO.getPriorityLevel());
        }
        conditions.orderByDesc("priority_level");
        List<SettlementRule> list = settlementMapper.selectList(conditions);
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(a -> {
                getSettlementRuleReceivable(a);
                setSettlementEnum(a);
            });
        }
        return list;
    }

    @Override
    public List<SettlementRule> findSettlementRuleByLevel(SettlementRule settlementRuleVO) {
        QueryWrapper<SettlementRule> conditions = new QueryWrapper<SettlementRule>();
        conditions.eq("is_delete", "0");
        conditions.ne("settlement_status", SettlementStatusEnum.CANCEL.getCode());
        if (StringUtils.isNotEmpty(settlementRuleVO.getMerchantCode())) {
            conditions.eq("merchant_code", settlementRuleVO.getMerchantCode());
        }
        if (StringUtils.isNotEmpty(settlementRuleVO.getProductCode())) {
            conditions.eq("product_code", settlementRuleVO.getProductCode());
        }
        conditions.and(wrapper -> wrapper.between("effective_date", settlementRuleVO.getEffectiveDate(), settlementRuleVO.getExpireDate()).or().between("expire_date", settlementRuleVO.getEffectiveDate(), settlementRuleVO.getExpireDate()));
        if (null != settlementRuleVO.getPriorityLevel()) {
            conditions.eq("priority_level", settlementRuleVO.getPriorityLevel());
        }
        List<SettlementRule> list = settlementMapper.selectList(conditions);
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(a -> {
                getSettlementRuleReceivable(a);
                setSettlementEnum(a);
            });
        }
        return list;
    }

    @Override
    public SettlementRule getSettlementByParam(GetSettlementRuleVO settlementRuleVO) {
        QueryWrapper<SettlementRule> conditions = new QueryWrapper<>();
        conditions.eq("is_delete", "0");
        conditions.eq("rule_code", settlementRuleVO.getRuleCode());
        SettlementRule rule = settlementMapper.selectOne(conditions);
        if (null != rule) {
            getSettlementRuleReceivable(rule);
            setSettlementEnum(rule);
        }
        return rule;
    }

    @Override
    public SettlementRule getSettlementByCodeLevel(SettlementRuleVO settlementRuleVO) {
        QueryWrapper<SettlementRule> conditions = new QueryWrapper<SettlementRule>();
        conditions.eq("is_delete", "0");
        conditions.eq("settlement_status", CommonUtil.STATUS_EFFECTIVE);
        if (StringUtils.isNotEmpty(settlementRuleVO.getProductCode())) {
            conditions.eq("product_code", settlementRuleVO.getProductCode());
        }
        if (null != settlementRuleVO.getCurrentTime()) {
            conditions.le("effective_date", settlementRuleVO.getCurrentTime());
        }
        if (null != settlementRuleVO.getCurrentTime()) {
            conditions.ge("expire_date", settlementRuleVO.getCurrentTime());
        }
        conditions.orderByDesc("priority_level");
        List<SettlementRule> list = settlementMapper.selectList(conditions);
        SettlementRule settlementRule = null;
        if (CollectionUtils.isNotEmpty(list)) {
            settlementRule = list.get(0);
            getSettlementRuleReceivable(settlementRule);
            setSettlementEnum(settlementRule);
        }
        return settlementRule;
    }

    @Override
    public List<SettlementRule> getIneffectiveRuleList(GetSettlementRuleVO settlementRuleVO) {
        QueryWrapper<SettlementRule> conditions = new QueryWrapper<SettlementRule>();
        conditions.eq("is_delete", "0");
        if (StringUtils.isNotEmpty(settlementRuleVO.getSettlementStatus())) {
            conditions.eq("settlement_status", CommonUtil.STATUS_NOT_EFFECTIVE);
        }
        if (null != settlementRuleVO.getEffectiveDate()) {
            conditions.le("effective_date", settlementRuleVO.getEffectiveDate());
        }
        List<SettlementRule> list = settlementMapper.selectList(conditions);
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(a -> {
                //补完枚举文本值
                setSettlementEnum(a);
            });
        }
        return list;

    }

    @Override
    public List<SettlementRule> getEffectiveRuleList(GetSettlementRuleVO settlementRuleVO) {
        QueryWrapper<SettlementRule> conditions = new QueryWrapper<SettlementRule>();
        conditions.eq("is_delete", "0");
        if (StringUtils.isNotEmpty(settlementRuleVO.getSettlementStatus())) {
            conditions.eq("settlement_status", CommonUtil.STATUS_EFFECTIVE);
        }
        if (null != settlementRuleVO.getExpireDate()) {
            conditions.le("expire_date", settlementRuleVO.getExpireDate());
        }
        List<SettlementRule> list = settlementMapper.selectList(conditions);
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(a -> {
                //补完枚举文本值
                setSettlementEnum(a);
            });
        }
        return list;
    }

    @Override
    public List<SettlementRule> getSettlementRuleByMerCode(List<String> listStr) {
        return settlementMapper.getSettlementRuleByMerCode(listStr);
    }

    @Override
    public List<SettlementRule> getSettlementRuleByMerProCode(List<String> merStr, List<String> proStr, String date) {
        return settlementMapper.getSettlementRuleByMerProCode(merStr, proStr, date);
    }


    public void test() {
        QueryWrapper<SettlementRule> conditions = new QueryWrapper<SettlementRule>();
        conditions.eq("rule_code", "");
        List<SettlementRule> mm = settlementMapper.selectList(conditions);
        for (SettlementRule settlement : mm) {
            settlement.setRuleCode(UUID.randomUUID().toString().replace("-", ""));
            settlementMapper.updateById(settlement);
        }
    }

    @Override
    public int add(SettlementRule settlement) {
        settlement.setSettlementStatus(CommonUtil.STATUS_NOT_EFFECTIVE);
        if (null != settlement.getEffectiveDate()) {
            LocalDate effDate = settlement.getEffectiveDate();
            if (effDate.isBefore(LocalDate.now()) || effDate.isEqual(LocalDate.now())) {
                // 已生效
                settlement.setSettlementStatus(CommonUtil.STATUS_EFFECTIVE);
            }
        }

        if (null != settlement.getExpireDate()) {
            LocalDate expireDate = settlement.getExpireDate();
            if (expireDate.isBefore(LocalDate.now()) || expireDate.isEqual(LocalDate.now())) {
                settlement.setSettlementStatus(CommonUtil.STATUS_EXPIRED);
            }
        }
        setSettlementEnum(settlement);

        if (StringUtils.isNotEmpty(settlement.getRuleName())) {
            //拼接creatTime时间戳(秒)后进行MD5运算 防止同名
            String content = settlement.getProductName() + settlement.getRuleName() + String.valueOf(settlement.getCreatedDt()).substring(0, 19);
            settlement.setRuleCode(DigestUtils.md5DigestAsHex(content.getBytes()).toUpperCase());
        }
        //清分规则(1:百分比 2:平台固定金额 3:商户固定金额)
        if (CommonUtil.RULE_PRE.equals(settlement.getClearingRule())) {
            if (StringUtils.isNotEmpty(settlement.getPlatformReceivable())) {
                settlement.setPlatformPre(new BigDecimal(settlement.getPlatformReceivable()));
            }
            if (StringUtils.isNotEmpty(settlement.getMerchantReceivable())) {
                settlement.setMerchantPre(new BigDecimal(settlement.getMerchantReceivable()));
            }
        }
        if (CommonUtil.RULE_FIX.equals(settlement.getClearingRule()) || CommonUtil.RULE_FIX_MERCHANT.equals(settlement.getClearingRule())) {
            if (StringUtils.isNotEmpty(settlement.getPlatformReceivable())) {
                Double receivable = Double.parseDouble(settlement.getPlatformReceivable()) * 100;
                settlement.setPlatformFix(Integer.valueOf(receivable.intValue()));
            }
            if (StringUtils.isNotEmpty(settlement.getMerchantReceivable())) {
                Double receivable = Double.parseDouble(settlement.getMerchantReceivable()) * 100;
                settlement.setMerchantFix(Integer.valueOf(receivable.intValue()));
            }
        }

        //线下结算规则(1:百分比 2:固定金额)
        if (CommonUtil.LINE_RULE_PRE.equals(settlement.getLineClearingRule())) {
            if (StringUtils.isNotEmpty(settlement.getLinePlatformReceivable())) {
                settlement.setLinePlatformPre(new BigDecimal(settlement.getLinePlatformReceivable()));
            }
            if (StringUtils.isNotEmpty(settlement.getLineMerchantReceivable())) {
                settlement.setLineMerchantPre(new BigDecimal(settlement.getLineMerchantReceivable()));
            }
        }
        if (CommonUtil.LINE_RULE_FIX.equals(settlement.getLineClearingRule())) {
            if (StringUtils.isNotEmpty(settlement.getLinePlatformReceivable())) {
                Double receivable = Double.parseDouble(settlement.getLinePlatformReceivable()) * 100;
                settlement.setLinePlatformFix(Integer.valueOf(receivable.intValue()));
            }
            if (StringUtils.isNotEmpty(settlement.getLineMerchantReceivable())) {
                Double receivable = Double.parseDouble(settlement.getLineMerchantReceivable()) * 100;
                settlement.setLineMerchantFix(Integer.valueOf(receivable.intValue()));
            }
        }

        if (StringUtils.isNotEmpty(settlement.getProductPrice())) {
            Double price = Double.parseDouble(settlement.getProductPrice()) * 100;
            settlement.setProductPrice(String.valueOf(price));
        }

        //新增时查询是否存在优先级相同的清分规则
        List<SettlementRule> list = findSettlementRuleByLevel(settlement);
        if (CollectionUtils.isNotEmpty(list)) {
            List<Long> strList = list.stream().map(SettlementRule::getId).collect(Collectors.toList());
            settlementMapper.updateRuleStatus(CommonUtil.STATUS_CANCEL, strList);
        }
        SettleCache.delCachePaymentSettleRule(settlement.getMerchantCode(),settlement.getProductCode());
        return settlementMapper.insert(settlement);
    }

    @Override
    public int update(SettlementRule settlement) {
        QueryWrapper<SettlementRule> conditions = new QueryWrapper<SettlementRule>();
        conditions.eq("settlement_status", "0");
        return settlementMapper.update(settlement, conditions);
    }

    @Override
    public int updateMerchantName(SettlementRule settlement) {
        QueryWrapper<SettlementRule> conditions = new QueryWrapper<SettlementRule>();
        conditions.eq("merchant_code", settlement.getMerchantCode());
        settlement.setCreatedDt(null);
        return settlementMapper.update(settlement, conditions);
    }

    @Override
    public int updateCancel(Long ruleId) {
        SettlementRule settlement = new SettlementRule();
        settlement.setCreatedDt(null);
        settlement.setId(ruleId);
        settlement.setSettlementStatus(CommonUtil.STATUS_CANCEL);
        settlement.setIsDelete(1);
        QueryWrapper<SettlementRule> conditions = new QueryWrapper<SettlementRule>();
        conditions.eq("id", ruleId);
        final SettlementRule settlementRule = settlementMapper.selectOne(conditions);
        if (null!=settlementRule) {
            SettleCache.delCachePaymentSettleRule(settlementRule.getMerchantCode(),settlementRule.getProductCode());
        }
        return settlementMapper.updateById(settlement);
    }

    @Override
    public int autoEffective() {
        DateTimeFormatter sdf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        GetSettlementRuleVO settlementRuleVO = new GetSettlementRuleVO();
        settlementRuleVO.setSettlementStatus(CommonUtil.STATUS_NOT_EFFECTIVE);
        settlementRuleVO.setEffectiveDate(sdf.format(LocalDateTime.now()));
        List<SettlementRule> result = getIneffectiveRuleList(settlementRuleVO);
        if (CollectionUtils.isNotEmpty(result)) {
            List<Long> strList = result.stream().map(SettlementRule::getId).collect(Collectors.toList());
            return settlementMapper.updateRuleStatus(CommonUtil.STATUS_EFFECTIVE, strList);
        }
        return 0;
    }

    @Override
    public int autoExpired() {
        DateTimeFormatter sdf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        GetSettlementRuleVO settlementRuleVO = new GetSettlementRuleVO();
        settlementRuleVO.setSettlementStatus(CommonUtil.STATUS_EFFECTIVE);
        settlementRuleVO.setExpireDate(sdf.format(LocalDateTime.now()));
        List<SettlementRule> result = getEffectiveRuleList(settlementRuleVO);
        if (CollectionUtils.isNotEmpty(result)) {
            List<Long> strList = result.stream().map(SettlementRule::getId).collect(Collectors.toList());
            for (SettlementRule settlementRule : result) {
                SettleCache.delCachePaymentSettleRule(settlementRule.getMerchantCode(),settlementRule.getProductCode());
            }
            return settlementMapper.updateRuleStatus(CommonUtil.STATUS_EXPIRED, strList);
        }
        return 0;
    }

    public void export(GetSettlementRuleVO settlementRuleVO, HttpServletRequest request, HttpServletResponse response) throws IOException {
        String[] title = {"规则编号", "优先级", "商户名称", "产品名称", "产品编码", "规则类型", "规则名称", "结算类型", "清分规则", "状态", "规则生效时间", "规则失效时间"};
        QueryWrapper<SettlementRule> conditions = new QueryWrapper<SettlementRule>();
        conditions.select("id", "priority_level", "merchant_name", "product_name","product_code", "rule_type", "rule_name", "settlement_type", "clearing_rule", "settlement_status", "effective_date", "expire_date");
        if (StringUtils.isNotEmpty(settlementRuleVO.getMerchantName())) {
            conditions.like("merchant_name", settlementRuleVO.getMerchantName());
        }
        if (StringUtils.isNotEmpty(settlementRuleVO.getProductName())) {
            conditions.like("product_name", settlementRuleVO.getProductName());
        }
        if (StringUtils.isNotEmpty(settlementRuleVO.getProductCode())) {
            conditions.eq("product_code", settlementRuleVO.getProductCode());
        }
        if (StringUtils.isNotEmpty(settlementRuleVO.getRuleCode())) {
            conditions.eq("rule_code", settlementRuleVO.getRuleCode());
        }
        if (StringUtils.isNotEmpty(settlementRuleVO.getRuleName())) {
            conditions.like("rule_name", settlementRuleVO.getRuleName());
        }
        if (StringUtils.isNotEmpty(settlementRuleVO.getRuleType())) {
            conditions.eq("rule_type", settlementRuleVO.getRuleType());
        }
        if (StringUtils.isNotEmpty(settlementRuleVO.getSettlementType())) {
            conditions.eq("settlement_type", settlementRuleVO.getSettlementType());
        }
        if (StringUtils.isNotEmpty(settlementRuleVO.getClearingRule())) {
            conditions.eq("clearing_rule", settlementRuleVO.getClearingRule());
        }
        if (StringUtils.isNotEmpty(settlementRuleVO.getSettlementStatus())) {
            conditions.eq("settlement_status", settlementRuleVO.getSettlementStatus());
        }
        if (StringUtils.isNotEmpty(settlementRuleVO.getEffectiveDate())) {
            conditions.ge("effective_date", settlementRuleVO.getEffectiveDate() + " 00:00:00");
        }
        if (StringUtils.isNotEmpty(settlementRuleVO.getExpireDate())) {
            conditions.le("expire_date", settlementRuleVO.getExpireDate() + " 23:59:59");
        }

        List<SettlementRule> list = settlementMapper.selectList(conditions);
        if (CollectionUtils.isNotEmpty(list)) {
            List<SettlementRuleExp> bList = list.stream().map(a -> {
                a.setSettlementStatus(SettlementStatusEnum.getDesc(a.getSettlementStatus()));
                a.setRuleType(SettlementRuleTypeEnum.getDesc(a.getRuleType()));
                a.setSettlementType(SettlementTypeEnum.getDesc(a.getSettlementType()));
                a.setClearingRule(SettlementClearRuleEnum.getDesc(a.getClearingRule()));
                return ObjectConvertUtil.convert(a, SettlementRuleExp.class).get();
            }).collect(Collectors.toList());
            List<Map<String, Object>> mapList = listConvert(bList);
            String fileName = "清分规则信息.xlsx";
            Workbook workbook = ExcelUtil.buildWorkbook("清分规则", title, mapList);
            ExcelUtil.exportExcle(request, response, workbook, fileName);
        }
    }

    /**
     * 数据转换
     *
     * @param list
     * @return
     */
    private List<Map<String, Object>> listConvert(List<SettlementRuleExp> list) {
        List<Map<String, Object>> list_map = new ArrayList<Map<String, Object>>();
        try {
            for (SettlementRuleExp t : list) {
                Field[] fields = t.getClass().getDeclaredFields();
                Map<String, Object> m = new LinkedHashMap<String, Object>();
                for (Field field : fields) {
                    String keyName = field.getName();
                    PropertyDescriptor pd = new PropertyDescriptor(keyName, t.getClass());
                    Method getMethod = pd.getReadMethod();// 获得getter方法
                    Object o = getMethod.invoke(t);// 执行get方法返回一个Object
                    m.put(keyName, o);
                }
                list_map.add(m);
            }
            return list_map;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    //查询返回结果数据转换
    private void getSettlementRuleReceivable(SettlementRule settlement) {
        if (null != settlement) {
            //清分规则(1:百分比 2:固定金额)
            if (SettlementClearRuleEnum.PERCENTAGE.getCode().equals(settlement.getClearingRule())) {
                settlement.setPlatformReceivable(String.valueOf(settlement.getPlatformPre()));
                settlement.setMerchantReceivable(String.valueOf(settlement.getMerchantPre()));
            } else if (SettlementClearRuleEnum.FIXED.getCode().equals(settlement.getClearingRule())
                    || SettlementClearRuleEnum.FIXED_MERCHANT.getCode().equals(settlement.getClearingRule())) {
                Double platformReceivable = settlement.getPlatformFix().doubleValue() / 100;
                settlement.setPlatformReceivable(String.valueOf(platformReceivable));
                Double merchantReceivable = settlement.getMerchantFix().doubleValue() / 100;
                settlement.setMerchantReceivable(String.valueOf(merchantReceivable));
            }
            //线下结算规则(1:百分比 2:固定金额)
            if (SettlementClearRuleEnum.PERCENTAGE.getCode().equals(settlement.getLineClearingRule())) {
                settlement.setLinePlatformReceivable(String.valueOf(settlement.getLinePlatformPre()));
                settlement.setLineMerchantReceivable(String.valueOf(settlement.getLineMerchantPre()));
            } else if (SettlementClearRuleEnum.FIXED.getCode().equals(settlement.getLineClearingRule())) {
                Double linePlatformFix = settlement.getLinePlatformFix().doubleValue() / 100;
                settlement.setLinePlatformReceivable(String.valueOf(linePlatformFix));
                Double lineMerchantFix = settlement.getLineMerchantFix().doubleValue() / 100;
                settlement.setLineMerchantReceivable(String.valueOf(lineMerchantFix));
            }
            if (StringUtils.isNotEmpty(settlement.getProductPrice())) {
                Double price = Double.parseDouble(settlement.getProductPrice()) / 100;
                settlement.setProductPrice(String.valueOf(price));
            }
        }
    }

    /**
     * 设置清分规则枚举值
     *
     * @param a
     */
    private void setSettlementEnum(SettlementRule a) {
        a.setSettlementStatusCn(SettlementStatusEnum.getDesc(a.getSettlementStatus()));
        a.setRuleTypeCn(SettlementRuleTypeEnum.getDesc(a.getRuleType()));
        a.setSettlementTypeCn(SettlementTypeEnum.getDesc(a.getSettlementType()));
        a.setClearingRuleCn(SettlementClearRuleEnum.getDesc(a.getClearingRule()));
        a.setLineClearingRuleCn(SettlementClearRuleEnum.getDesc(a.getLineClearingRule()));
    }

    /**
     * 根据交易中台商品编码批量查询清分规则
     *
     * @param productCodes
     * @return
     */
    @Override
    public List<SettlementRule> getRulesByProductCodes(List<String> productCodes) {
        QueryWrapper<SettlementRule> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("product_code", productCodes);
        queryWrapper.eq("settlement_status", SettlementStatusEnum.EFFECTIVE.getCode());
        queryWrapper.eq("is_delete", "0");

        List<SettlementRule> list = settlementMapper.selectList(queryWrapper);
        if (!list.isEmpty()) {
            Map<String, SettlementRule> map = new HashMap<>();
            list.forEach(settlementRule -> {
                // 取得优先级最高规则
                if (null != map.get(settlementRule.getProductCode())) {
                    if (settlementRule.getPriorityLevel() > map.get(settlementRule.getProductCode()).getPriorityLevel()) {
                        map.put(settlementRule.getProductCode(), settlementRule);
                    }
                } else {
                    map.put(settlementRule.getProductCode(), settlementRule);
                }
            });
            list = new ArrayList<>(map.values());
            return list;
        }
        return null;
    }

    @Override
    public String addRule(OpenAddRuleVO openAddRuleVO) {
        BusinessErrorInfoEnum.SETTLE_RULE_RULE_ORDER_SOURCE_NOT_SUPPORT.assertIsTrue(OPEN_SETTLE_RULE_SOURCE.contains(openAddRuleVO.getOrderSource()));
        Result<ProductBO> productInfo = merchantPaymentChannelService.getProductInfo(openAddRuleVO.getProductCode());
        BusinessErrorInfoEnum.SETTLE_RULE_RULE_PRODUCT_NOT_EXIT.assertIsTrue(productInfo.getRet() == 0 && productInfo.getData() != null);
        BusinessErrorInfoEnum.SETTLE_RULE_RULE_MERCHANT_OR_PRODUCT_ERROR.assertIsTrue(productInfo.getData().getMerchantCode().equals(openAddRuleVO.getMerchantCode())
                && productInfo.getData().getProductCode().equals(openAddRuleVO.getProductCode()));
        BusinessErrorInfoEnum.SETTLE_RULE_CLEARING_CYCLE_MODE_NOT_SUPPORT.assertIsTrue(openAddRuleVO.getClearingCycleMode().equals("1") ||
                openAddRuleVO.getClearingCycleMode().equals("2"));
        SettlementRule settlementRule = new SettlementRule();
        settlementRule.setMerchantCode(openAddRuleVO.getMerchantCode());
        settlementRule.setMerchantName(openAddRuleVO.getMerchantName());
        settlementRule.setProductCode(openAddRuleVO.getProductCode());
        settlementRule.setProductName(productInfo.getData().getProductName());
        settlementRule.setProductCodeBusiness(productInfo.getData().getProductCodeBusiness());
        settlementRule.setRuleType(CommonUtil.RULE_PRODUCT_TYPE);
        settlementRule.setRuleTypeCn("产品");
        // 写死结算类型为清分
        settlementRule.setSettlementType(SettlementTypeEnum.CLEARING.getCode());
        settlementRule.setSettlementTypeCn(SettlementTypeEnum.CLEARING.getDesc());
        settlementRule.setRuleCode(DateTimeUtil.format(LocalDateTime.now(), "yyyyMMdd") + idGenerateUtil.getUniqueIDByKey("SETTLERULECODE", "%07d", true, TimeUnit.DAYS, 1L));
        settlementRule.setRuleName(this.getRuleName(settlementRule.getProductName()));
        settlementRule.setSettlementStatus(CommonUtil.STATUS_EFFECTIVE);
        settlementRule.setSettlementStatusCn("已生效");
        settlementRule.setClearingCycleMode(openAddRuleVO.getClearingCycleMode());
        settlementRule.setClearingCycleValue(openAddRuleVO.getClearingCycleValue());
        settlementRule.setClearingRule(openAddRuleVO.getClearingRule());
        if (settlementRule.getClearingCycleMode().equals("2")) {
            // 按月清分，清分周期扩展值不允许为空
            BusinessErrorInfoEnum.SETTLE_RULE_CLEARINGCYCLEVALUEEXT_NULL.assertIsTrue(null != openAddRuleVO.getClearingCycleValueExt() && openAddRuleVO.getClearingCycleValueExt() <= 28);
            settlementRule.setClearingCycleValueExt(openAddRuleVO.getClearingCycleValueExt());
        }
        BusinessErrorInfoEnum.SETTLE_RULE_NOT_SUPPORT_CLEARING_RULE_NULL.assertIsTrue(settlementRule.getClearingRule().equals(CommonUtil.RULE_PRE)
                || settlementRule.getClearingRule().equals(CommonUtil.RULE_FIX) || settlementRule.getClearingRule().equals(CommonUtil.RULE_FIX_MERCHANT));
        //清分规则(1:百分比 2:平台固定金额 3:商户固定金额)
        if (CommonUtil.RULE_PRE.equals(settlementRule.getClearingRule())) {
            BusinessErrorInfoEnum.SETTLE_RULE_RULE_PRE_RECEIVABLE_NOT_NULL.assertIsTrue(openAddRuleVO.getPlatformPre() != null &&
                    openAddRuleVO.getMerchantPre() != null);
            BusinessErrorInfoEnum.SETTLE_RULE_RULE_PRE_RECEIVABLE_ERROR.assertIsTrue(openAddRuleVO.getPlatformPre().compareTo(new BigDecimal(100)) <= 0
                    && openAddRuleVO.getMerchantPre().compareTo(new BigDecimal(100)) <= 0 &&
                    openAddRuleVO.getPlatformPre().add(openAddRuleVO.getMerchantPre()).compareTo(new BigDecimal(100)) == 0);
            settlementRule.setClearingRuleCn("百分比");
            settlementRule.setPlatformPre(openAddRuleVO.getPlatformPre());
            settlementRule.setMerchantPre(openAddRuleVO.getMerchantPre());
        }
        if (CommonUtil.RULE_FIX.equals(openAddRuleVO.getClearingRule())) {
            BusinessErrorInfoEnum.SETTLE_RULE_RULE_FIX_PLATFORM_FIX_NOT_NULL.assertIsTrue(openAddRuleVO.getPlatformFix() != null && openAddRuleVO.getPlatformFix() > 0);
            settlementRule.setClearingRuleCn("平台固定金额");
            settlementRule.setPlatformFix(openAddRuleVO.getPlatformFix());
            settlementRule.setMerchantFix(0);
        }
        if (CommonUtil.RULE_FIX_MERCHANT.equals(openAddRuleVO.getClearingRule())) {
            BusinessErrorInfoEnum.SETTLE_RULE_RULE_FIX_MERCHANT_FIX_NOT_NULL.assertIsTrue(openAddRuleVO.getMerchantFix() != null && openAddRuleVO.getMerchantFix() > 0);
            settlementRule.setClearingRuleCn("商户固定金额");
            settlementRule.setMerchantFix(openAddRuleVO.getMerchantFix());
            settlementRule.setPlatformFix(0);

        }
        if (null != openAddRuleVO.getProductPrice()) {
            settlementRule.setProductPrice(String.valueOf(openAddRuleVO.getProductPrice()));
        }
        // 默认设置有效期5年
        settlementRule.setEffectiveDate(LocalDate.now());
        settlementRule.setExpireDate(LocalDate.now().plusYears(5));
        settlementRule.setPriorityLevel(1);

        QueryWrapper<SettlementRule> conditions = new QueryWrapper<>();
        conditions.eq("product_code", settlementRule.getProductCode());
        conditions.eq("settlement_status", SettlementStatusEnum.EFFECTIVE.getCode());

        final List<SettlementRule> settlementRules = settlementMapper.selectList(conditions);
        if(CollectionUtils.isNotEmpty(settlementRules)){
            SettlementRule updateEntity = new SettlementRule();
            updateEntity.setSettlementStatus(SettlementStatusEnum.CANCEL.getCode());
            updateEntity.setIsDelete(1);
            settlementMapper.update(updateEntity, conditions);
        }
        SettleCache.delCachePaymentSettleRule(settlementRule.getMerchantCode(),settlementRule.getProductCode());
        settlementMapper.insert(settlementRule);
        return settlementRule.getRuleCode();
    }

    @Override
    public void openDeleteRule(OpenDeleteRuleVO openDeleteRuleVO) {
        BusinessErrorInfoEnum.SETTLE_RULE_RULE_ORDER_SOURCE_NOT_SUPPORT.assertIsTrue(OPEN_SETTLE_RULE_SOURCE.contains(openDeleteRuleVO.getOrderSource()));
        settlementMapper.deleteOpenBatch(openDeleteRuleVO.getProducts());
        for (OpenDeleteRuleVO.Product p : openDeleteRuleVO.getProducts()) {
            SettleCache.delCachePaymentSettleRule(p.getMerchantCode(),p.getProductCode());
        }
    }

    private String getRuleName(String productName) {
        if (StringUtils.isEmpty(productName)) {
            return "清分规则";
        }
        if (productName.length() < 28) {
            return productName + "-清分";
        }
        return productName.substring(0, 28) + "-清分";
    }
}
